#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QCheckBox>
#include "test2.h"
#include <QTimer>
#include "pixmapwidget.h"

MainWindow::MainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{
  std::srand(QDateTime::currentDateTime().toMSecsSinceEpoch()/1000.0);
  ui->setupUi(this);

  setup1();
}



MainWindow::~MainWindow()
{
  delete ui;
  delete m_customPlot;
  delete customPlot;
}

void MainWindow::titleDoubleClick(QMouseEvent* event)
{
  Q_UNUSED(event)
  if (QCPTextElement *title = qobject_cast<QCPTextElement*>(sender()))
  {
    // Set the plot title by double clicking on it
    bool ok;
    QString newTitle = QInputDialog::getText(this, "QCustomPlot example", "New plot title:", QLineEdit::Normal, title->text(), &ok);
    if (ok)
    {
      title->setText(newTitle);
      m_customPlot->replot();
    }
  }
}

void MainWindow::axisLabelDoubleClick(QCPAxis *axis, QCPAxis::SelectablePart part)
{
  // Set an axis label by double clicking on it
  if (part == QCPAxis::spAxisLabel) // only react when the actual axis label is clicked, not tick label or axis backbone
  {
    bool ok;
    QString newLabel = QInputDialog::getText(this, "QCustomPlot example", "New axis label:", QLineEdit::Normal, axis->label(), &ok);
    if (ok)
    {
      axis->setLabel(newLabel);
      m_customPlot->replot();
    }
  }
}

void MainWindow::legendDoubleClick(QCPLegend *legend, QCPAbstractLegendItem *item)
{
  // Rename a graph by double clicking on its legend item
  Q_UNUSED(legend)
  if (item) // only react if item was clicked (user could have clicked on border padding of legend where there is no item, then item is 0)
  {
    QCPPlottableLegendItem *plItem = qobject_cast<QCPPlottableLegendItem*>(item);
    bool ok;
    QString newName = QInputDialog::getText(this, "QCustomPlot example", "New graph name:", QLineEdit::Normal, plItem->plottable()->name(), &ok);
    if (ok)
    {
      plItem->plottable()->setName(newName);
      m_customPlot->replot();
    }
  }
}

void MainWindow::selectionChanged()
{
  /*
   normally, axis base line, axis tick labels and axis labels are selectable separately, but we want
   the user only to be able to select the axis as a whole, so we tie the selected states of the tick labels
   and the axis base line together. However, the axis label shall be selectable individually.
   
   The selection state of the left and right axes shall be synchronized as well as the state of the
   bottom and top axes.
   
   Further, we want to synchronize the selection of the graphs with the selection state of the respective
   legend item belonging to that graph. So the user can select a graph by either clicking on the graph itself
   or on its legend item.
  */
  
  // make top and bottom axes be selected synchronously, and handle axis and tick labels as one selectable object:
  if (m_customPlot->xAxis->selectedParts().testFlag(QCPAxis::spAxis) || m_customPlot->xAxis->selectedParts().testFlag(QCPAxis::spTickLabels) ||
      m_customPlot->xAxis2->selectedParts().testFlag(QCPAxis::spAxis) || m_customPlot->xAxis2->selectedParts().testFlag(QCPAxis::spTickLabels))
  {
    m_customPlot->xAxis2->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
    m_customPlot->xAxis->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
  }
  // make left and right axes be selected synchronously, and handle axis and tick labels as one selectable object:
  if (m_customPlot->yAxis->selectedParts().testFlag(QCPAxis::spAxis) || m_customPlot->yAxis->selectedParts().testFlag(QCPAxis::spTickLabels) ||
      m_customPlot->yAxis2->selectedParts().testFlag(QCPAxis::spAxis) || m_customPlot->yAxis2->selectedParts().testFlag(QCPAxis::spTickLabels))
  {
    m_customPlot->yAxis2->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
    m_customPlot->yAxis->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
  }
  
  // synchronize selection of graphs with selection of corresponding legend items:
  for (int i=0; i<m_customPlot->graphCount(); ++i)
  {
    QCPGraph *graph = m_customPlot->graph(i);
    QCPPlottableLegendItem *item = m_customPlot->legend->itemWithPlottable(graph);
    if (item->selected() || graph->selected())
    {
      item->setSelected(true);
      graph->setSelection(QCPDataSelection(graph->data()->dataRange()));
    }
  }
}

void MainWindow::mousePress()
{
  // if an axis is selected, only allow the direction of that axis to be dragged
  // if no axis is selected, both directions may be dragged
  
  if (m_customPlot->xAxis->selectedParts().testFlag(QCPAxis::spAxis))
    m_customPlot->axisRect()->setRangeDrag(m_customPlot->xAxis->orientation());
  else if (m_customPlot->yAxis->selectedParts().testFlag(QCPAxis::spAxis))
    m_customPlot->axisRect()->setRangeDrag(m_customPlot->yAxis->orientation());
  else
    m_customPlot->axisRect()->setRangeDrag(Qt::Horizontal|Qt::Vertical);
}

void MainWindow::mouseWheel()
{
  // if an axis is selected, only allow the direction of that axis to be zoomed
  // if no axis is selected, both directions may be zoomed
  
  if (m_customPlot->xAxis->selectedParts().testFlag(QCPAxis::spAxis))
    m_customPlot->axisRect()->setRangeZoom(m_customPlot->xAxis->orientation());
  else if (m_customPlot->yAxis->selectedParts().testFlag(QCPAxis::spAxis))
    m_customPlot->axisRect()->setRangeZoom(m_customPlot->yAxis->orientation());
  else
    m_customPlot->axisRect()->setRangeZoom(Qt::Horizontal|Qt::Vertical);
}

void MainWindow::addRandomGraph()
{
  int n = 50; // number of points in graph
  double xScale = (std::rand()/(double)RAND_MAX + 0.5)*2;
  double yScale = (std::rand()/(double)RAND_MAX + 0.5)*2;
  double xOffset = (std::rand()/(double)RAND_MAX - 0.5)*4;
  double yOffset = (std::rand()/(double)RAND_MAX - 0.5)*10;
  double r1 = (std::rand()/(double)RAND_MAX - 0.5)*2;
  double r2 = (std::rand()/(double)RAND_MAX - 0.5)*2;
  double r3 = (std::rand()/(double)RAND_MAX - 0.5)*2;
  double r4 = (std::rand()/(double)RAND_MAX - 0.5)*2;
  QVector<double> x(n), y(n);
  for (int i=0; i<n; i++)
  {
    x[i] = (i/(double)n-0.5)*10.0*xScale + xOffset;
    y[i] = (qSin(x[i]*r1*5)*qSin(qCos(x[i]*r2)*r4*3)+r3*qCos(qSin(x[i])*r4*2))*yScale + yOffset;
  }
  
  m_customPlot->addGraph();
  m_customPlot->graph()->setName(QString("New graph %1").arg(m_customPlot->graphCount()-1));
  m_customPlot->graph()->setData(x, y);
  m_customPlot->graph()->setLineStyle((QCPGraph::LineStyle)(std::rand()%5+1));
  if (std::rand()%100 > 50)
    m_customPlot->graph()->setScatterStyle(QCPScatterStyle((QCPScatterStyle::ScatterShape)(std::rand()%14+1)));
  QPen graphPen;
  graphPen.setColor(QColor(std::rand()%245+10, std::rand()%245+10, std::rand()%245+10));
  graphPen.setWidthF(std::rand()/(double)RAND_MAX*2+1);
  m_customPlot->graph()->setPen(graphPen);
  m_customPlot->replot();
}

void MainWindow::removeSelectedGraph()
{
  if (m_customPlot->selectedGraphs().size() > 0)
  {
    m_customPlot->removeGraph(m_customPlot->selectedGraphs().first());
    m_customPlot->replot();
  }
}

void MainWindow::removeAllGraphs()
{
  m_customPlot->clearGraphs();
  m_customPlot->replot();
}

void MainWindow::contextMenuRequest(QPoint pos)
{
  QMenu *menu = new QMenu(this);
  menu->setAttribute(Qt::WA_DeleteOnClose);
  
  if (m_customPlot->legend->selectTest(pos, false) >= 0) // context menu on legend requested
  {
    menu->addAction("Move to top left", this, SLOT(moveLegend()))->setData((int)(Qt::AlignTop|Qt::AlignLeft));
    menu->addAction("Move to top center", this, SLOT(moveLegend()))->setData((int)(Qt::AlignTop|Qt::AlignHCenter));
    menu->addAction("Move to top right", this, SLOT(moveLegend()))->setData((int)(Qt::AlignTop|Qt::AlignRight));
    menu->addAction("Move to bottom right", this, SLOT(moveLegend()))->setData((int)(Qt::AlignBottom|Qt::AlignRight));
    menu->addAction("Move to bottom left", this, SLOT(moveLegend()))->setData((int)(Qt::AlignBottom|Qt::AlignLeft));
  } else  // general context menu on graphs requested
  {
    menu->addAction("Add random graph", this, SLOT(addRandomGraph()));
    if (m_customPlot->selectedGraphs().size() > 0)
      menu->addAction("Remove selected graph", this, SLOT(removeSelectedGraph()));
    if (m_customPlot->graphCount() > 0)
      menu->addAction("Remove all graphs", this, SLOT(removeAllGraphs()));
  }
  
  menu->popup(m_customPlot->mapToGlobal(pos));
}

void MainWindow::moveLegend()
{
  if (QAction* contextAction = qobject_cast<QAction*>(sender())) // make sure this slot is really called by a context menu action, so it carries the data we need
  {
    bool ok;
    int dataInt = contextAction->data().toInt(&ok);
    if (ok)
    {
      m_customPlot->axisRect()->insetLayout()->setInsetAlignment(0, (Qt::Alignment)dataInt);
      m_customPlot->replot();
    }
  }
}

void MainWindow::graphClicked(QCPAbstractPlottable *plottable, int dataIndex)
{
  // since we know we only have QCPGraphs in the plot, we can immediately access interface1D()
  // usually it's better to first check whether interface1D() returns non-zero, and only then use it.
  double dataValue = plottable->interface1D()->dataMainValue(dataIndex);
  QString message = QString("Clicked on graph '%1' at data point #%2 with value %3.").arg(plottable->name()).arg(dataIndex).arg(dataValue);
  ui->statusBar->showMessage(message, 2500);
}


void MainWindow::on_pushButton_addGraph_clicked()
{
    int n = 50; // number of points in graph
    double xScale = (std::rand()/(double)RAND_MAX + 0.5)*2;
    double yScale = (std::rand()/(double)RAND_MAX + 0.5)*2;
    double xOffset = (std::rand()/(double)RAND_MAX - 0.5)*4;
    double yOffset = (std::rand()/(double)RAND_MAX - 0.5)*10;
    double r1 = (std::rand()/(double)RAND_MAX - 0.5)*2;
    double r2 = (std::rand()/(double)RAND_MAX - 0.5)*2;
    double r3 = (std::rand()/(double)RAND_MAX - 0.5)*2;
    double r4 = (std::rand()/(double)RAND_MAX - 0.5)*2;
    QVector<double> x(n), y(n);
    for (int i=0; i<n; i++)
    {
      x[i] = (i/(double)n-0.5)*10.0*xScale + xOffset;
      y[i] = (qSin(x[i]*r1*5)*qSin(qCos(x[i]*r2)*r4*3)+r3*qCos(qSin(x[i])*r4*2))*yScale + yOffset;
    }

    m_customPlot->addGraph();
    m_customPlot->graph()->setName(QString("New graph %1").arg(m_customPlot->graphCount()-1));
    m_customPlot->graph()->setData(x, y);
//    m_customPlot->graph()->setLineStyle((QCPGraph::LineStyle)(std::rand()%5+1));
    m_customPlot->graph()->setScatterStyle(QCPScatterStyle((QCPScatterStyle::ScatterShape)m_scatterStyle));
    QPen graphPen;
    graphPen.setColor(QColor(std::rand()%245+10, std::rand()%245+10, std::rand()%245+10));
    graphPen.setWidthF(std::rand()/(double)RAND_MAX*2+1);
    m_customPlot->graph()->setPen(graphPen);
    m_customPlot->replot();
}

void MainWindow::on_pushButton_updateGraph_clicked()
{
    removeAllGraphs();
    on_pushButton_addGraph_clicked();

//    // add the text label at the top:
//    QCPItemText *textLabel = new QCPItemText(m_customPlot);
//    textLabel->setPositionAlignment(Qt::AlignTop|Qt::AlignHCenter);
//    textLabel->position->setType(QCPItemPosition::ptAxisRectRatio);
//    textLabel->position->setCoords(0.5, 0); // place position at center/top of axis rect
//    textLabel->setText("Text Item Demo");
//    textLabel->setFont(QFont(font().family(), 16)); // make font a bit larger
//    textLabel->setPen(QPen(Qt::black)); // show black border around text

//    // add the arrow:
//    QCPItemLine *arrow = new QCPItemLine(m_customPlot);
//    arrow->start->setParentAnchor(textLabel->bottom);
//    arrow->end->setCoords(4, 1.6); // point to (4, 1.6) in x-y-plot coordinates
//    arrow->setHead(QCPLineEnding::esSpikeArrow);

}

void MainWindow::on_checkBox_dataDot_clicked(bool checked)
{
    if(checked)
    {
        m_scatterStyle = 4;
    }else
    {
        m_scatterStyle = 0;
    }
}

void MainWindow::bracketDataSlot()
{
    double secs = QCPAxisTickerDateTime::dateTimeToKey(QDateTime::currentDateTime());

    // update data to make phase move:
    int n = 500;
    double phase = secs*5;
    double k = 3;
    QVector<double> x(n), y(n);
    for (int i=0; i<n; ++i)
    {
      x[i] = i/(double)(n-1)*34 - 17;
      y[i] = qExp(-x[i]*x[i]/20.0)*qSin(k*x[i]+phase);
    }
    customPlot->graph()->setData(x, y);

    itemDemoPhaseTracer->setGraphKey((8*M_PI+fmod(M_PI*1.5-phase, 6*M_PI))/k);

    customPlot->replot();

    // calculate frames per second:
    double key = secs;
    static double lastFpsKey;
    static int frameCount;
    ++frameCount;
    if (key-lastFpsKey > 2) // average fps over 2 seconds
    {
      ui->statusBar->showMessage(
            QString("%1 FPS, Total Data points: %2")
            .arg(frameCount/(key-lastFpsKey), 0, 'f', 0)
            .arg(customPlot->graph(0)->data()->size())
            , 0);
      lastFpsKey = key;
      frameCount = 0;
    }
}

void MainWindow::setup1()
{
    m_customPlot = new WGCustomPlotWidget(this);
//    TTKGrabItemWidget *move = new TTKGrabItemWidget(m_customPlot);
    QVBoxLayout* mainLayout = new QVBoxLayout(ui->customPlot);
    mainLayout->setMargin(0);
    mainLayout->addWidget(m_customPlot);
    mainLayout->setStretch(0, 1);

    m_customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectAxes |
                                    QCP::iSelectLegend | QCP::iSelectPlottables);
    m_customPlot->xAxis->setRange(-8, 8);
    m_customPlot->yAxis->setRange(-5, 5);
    m_customPlot->axisRect()->setupFullAxesBox();

    m_customPlot->plotLayout()->insertRow(0);// 在轴矩形上方插入一个空行
    QCPTextElement *title = new QCPTextElement(m_customPlot, "Interaction Example", QFont("sans", 17, QFont::Bold));
    m_customPlot->plotLayout()->addElement(0, 0, title);// 将标题放置在我们刚刚创建的空单元格中

    m_customPlot->xAxis->setLabel("x Axis");
    m_customPlot->yAxis->setLabel("y Axis");
    m_customPlot->legend->setVisible(true);
    QFont legendFont = font();
    legendFont.setPointSize(10);
    m_customPlot->legend->setFont(legendFont);
    m_customPlot->legend->setSelectedFont(legendFont);
    m_customPlot->legend->setSelectableParts(QCPLegend::spItems); // legend box shall not be selectable, only legend items

    addRandomGraph();
    addRandomGraph();
    addRandomGraph();
    addRandomGraph();
    addRandomGraph();
    addRandomGraph();
    addRandomGraph();
    m_customPlot->rescaleAxes();

    m_customPlot->plotLayout()->insertRow(1);
    QCPLayoutGrid *subLayout = new QCPLayoutGrid;
    m_customPlot->plotLayout()->addElement(1, 0, subLayout);
    subLayout->setMargins(QMargins(25, 0, 5, 5));
    subLayout->addElement(1, 0, m_customPlot->legend);
    m_customPlot->legend->setWrap(3);//图例最大列/行数
    // 将图例的填充顺序改为从上到下按行填充：
    m_customPlot->legend->setFillOrder(QCPLegend::foColumnsFirst);
    // 将图例的行拉伸因子设置为非常小的值，使其高度最小：
    m_customPlot->plotLayout()->setRowStretchFactor(1, 0.001);

    // connect slot that ties some axis selections together (especially opposite axes):
    connect(m_customPlot, SIGNAL(selectionChangedByUser()), this, SLOT(selectionChanged()));
    // connect slots that takes care that when an axis is selected, only that direction can be dragged and zoomed:
    connect(m_customPlot, SIGNAL(mousePress(QMouseEvent*)), this, SLOT(mousePress()));
    connect(m_customPlot, SIGNAL(mouseWheel(QWheelEvent*)), this, SLOT(mouseWheel()));

    // make bottom and left axes transfer their ranges to top and right axes:
    connect(m_customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), m_customPlot->xAxis2, SLOT(setRange(QCPRange)));
    connect(m_customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), m_customPlot->yAxis2, SLOT(setRange(QCPRange)));

    // connect some interaction slots:
    connect(m_customPlot, SIGNAL(axisDoubleClick(QCPAxis*,QCPAxis::SelectablePart,QMouseEvent*)), this, SLOT(axisLabelDoubleClick(QCPAxis*,QCPAxis::SelectablePart)));
    connect(m_customPlot, SIGNAL(legendDoubleClick(QCPLegend*,QCPAbstractLegendItem*,QMouseEvent*)), this, SLOT(legendDoubleClick(QCPLegend*,QCPAbstractLegendItem*)));
    connect(title, SIGNAL(doubleClicked(QMouseEvent*)), this, SLOT(titleDoubleClick(QMouseEvent*)));

    // connect slot that shows a message in the status bar when a graph is clicked:
    connect(m_customPlot, SIGNAL(plottableClick(QCPAbstractPlottable*,int,QMouseEvent*)), this, SLOT(graphClicked(QCPAbstractPlottable*,int)));

    // setup policy and connect slot for context menu popup:
    m_customPlot->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(m_customPlot, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequest(QPoint)));

    if(ui->checkBox_dataDot->isChecked())
    {
        m_scatterStyle = 4;
    }else
    {
        m_scatterStyle = 0;
    }
}

void MainWindow::setup2()
{
    customPlot = new QCustomPlot(this);
    QVBoxLayout* mainLayout = new QVBoxLayout(ui->customPlot);
    mainLayout->setMargin(0);
    mainLayout->addWidget(customPlot);
    mainLayout->setStretch(0, 1);

    customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
    QCPGraph *graph = customPlot->addGraph();
    int n = 500;
    double phase = 0;
    double k = 3;
    QVector<double> x(n), y(n);
    for (int i=0; i<n; ++i)
    {
      x[i] = i/(double)(n-1)*34 - 17;
      y[i] = qExp(-x[i]*x[i]/20.0)*qSin(k*x[i]+phase);
    }
    graph->setData(x, y);
    graph->setPen(QPen(Qt::blue));
    graph->rescaleKeyAxis();
    customPlot->yAxis->setRange(-1.45, 1.65);
    customPlot->xAxis->grid()->setZeroLinePen(Qt::NoPen);

    // add the bracket at the top:
    QCPItemBracket *bracket = new QCPItemBracket(customPlot);
    bracket->left->setCoords(-8, 1.1);
    bracket->right->setCoords(8, 1.1);
    bracket->setLength(13);

    // add the text label at the top:
    QCPItemText *wavePacketText = new QCPItemText(customPlot);
    wavePacketText->position->setParentAnchor(bracket->center);
    wavePacketText->position->setCoords(0, -10); // move 10 pixels to the top from bracket center anchor
    wavePacketText->setPositionAlignment(Qt::AlignBottom|Qt::AlignHCenter);
    wavePacketText->setText("Wavepacket");
    wavePacketText->setFont(QFont(font().family(), 10));

    // add the phase tracer (red circle) which sticks to the graph data (and gets updated in bracketDataSlot by timer event):
    QCPItemTracer *phaseTracer = new QCPItemTracer(customPlot);
    itemDemoPhaseTracer = phaseTracer; // so we can access it later in the bracketDataSlot for animation
    phaseTracer->setGraph(graph);
    phaseTracer->setGraphKey((M_PI*1.5-phase)/k);
    phaseTracer->setInterpolating(true);
    phaseTracer->setStyle(QCPItemTracer::tsCircle);
    phaseTracer->setPen(QPen(Qt::red));
    phaseTracer->setBrush(Qt::red);
    phaseTracer->setSize(7);

    // add label for phase tracer:
    QCPItemText *phaseTracerText = new QCPItemText(customPlot);
    phaseTracerText->position->setType(QCPItemPosition::ptAxisRectRatio);
    phaseTracerText->setPositionAlignment(Qt::AlignRight|Qt::AlignBottom);
    phaseTracerText->position->setCoords(1.0, 0.95); // lower right corner of axis rect
    phaseTracerText->setText("Points of fixed\nphase define\nphase velocity vp");
    phaseTracerText->setTextAlignment(Qt::AlignLeft);
    phaseTracerText->setFont(QFont(font().family(), 9));
    phaseTracerText->setPadding(QMargins(8, 0, 0, 0));

    // add arrow pointing at phase tracer, coming from label:
    QCPItemCurve *phaseTracerArrow = new QCPItemCurve(customPlot);
    phaseTracerArrow->start->setParentAnchor(phaseTracerText->left);
    phaseTracerArrow->startDir->setParentAnchor(phaseTracerArrow->start);
    phaseTracerArrow->startDir->setCoords(-40, 0); // direction 30 pixels to the left of parent anchor (tracerArrow->start)
    phaseTracerArrow->end->setParentAnchor(phaseTracer->position);
    phaseTracerArrow->end->setCoords(10, 10);
    phaseTracerArrow->endDir->setParentAnchor(phaseTracerArrow->end);
    phaseTracerArrow->endDir->setCoords(30, 30);
    phaseTracerArrow->setHead(QCPLineEnding::esSpikeArrow);
    phaseTracerArrow->setTail(QCPLineEnding(QCPLineEnding::esBar, (phaseTracerText->bottom->pixelPosition().y()-phaseTracerText->top->pixelPosition().y())*0.85));

    // add the group velocity tracer (green circle):
    QCPItemTracer *groupTracer = new QCPItemTracer(customPlot);
    groupTracer->setGraph(graph);
    groupTracer->setGraphKey(5.5);
    groupTracer->setInterpolating(true);
    groupTracer->setStyle(QCPItemTracer::tsCircle);
    groupTracer->setPen(QPen(Qt::green));
    groupTracer->setBrush(Qt::green);
    groupTracer->setSize(7);

    // add label for group tracer:
    QCPItemText *groupTracerText = new QCPItemText(customPlot);
    groupTracerText->position->setType(QCPItemPosition::ptAxisRectRatio);
    groupTracerText->setPositionAlignment(Qt::AlignRight|Qt::AlignTop);
    groupTracerText->position->setCoords(1.0, 0.20); // lower right corner of axis rect
    groupTracerText->setText("Fixed positions in\nwave packet define\ngroup velocity vg");
    groupTracerText->setTextAlignment(Qt::AlignLeft);
    groupTracerText->setFont(QFont(font().family(), 9));
    groupTracerText->setPadding(QMargins(8, 0, 0, 0));

    // add arrow pointing at group tracer, coming from label:
    QCPItemCurve *groupTracerArrow = new QCPItemCurve(customPlot);
    groupTracerArrow->start->setParentAnchor(groupTracerText->left);
    groupTracerArrow->startDir->setParentAnchor(groupTracerArrow->start);
    groupTracerArrow->startDir->setCoords(-40, 0); // direction 30 pixels to the left of parent anchor (tracerArrow->start)
    groupTracerArrow->end->setCoords(5.5, 0.4);
    groupTracerArrow->endDir->setParentAnchor(groupTracerArrow->end);
    groupTracerArrow->endDir->setCoords(0, -40);
    groupTracerArrow->setHead(QCPLineEnding::esSpikeArrow);
    groupTracerArrow->setTail(QCPLineEnding(QCPLineEnding::esBar, (groupTracerText->bottom->pixelPosition().y()-groupTracerText->top->pixelPosition().y())*0.85));

    // add dispersion arrow:
    QCPItemCurve *arrow = new QCPItemCurve(customPlot);
    arrow->start->setCoords(1, -1.1);
    arrow->startDir->setCoords(-1, -1.3);
    arrow->endDir->setCoords(-5, -0.3);
    arrow->end->setCoords(-10, -0.2);
    arrow->setHead(QCPLineEnding::esSpikeArrow);

    // add the dispersion arrow label:
    QCPItemText *dispersionText = new QCPItemText(customPlot);
    dispersionText->position->setCoords(-6, -0.9);
    dispersionText->setRotation(40);
    dispersionText->setText("Dispersion with\nvp < vg");
    dispersionText->setFont(QFont(font().family(), 10));

    // setup a timer that repeatedly calls MainWindow::bracketDataSlot:
    //connect(&dataTimer, SIGNAL(timeout()), this, SLOT(bracketDataSlot()));
    //dataTimer.start(0); // Interval 0 means to refresh as fast as possible
}

void MainWindow::setup3()
{
    // 创建可视化对象
    QCustomPlot* plot = new QCustomPlot(this);
    QVBoxLayout* mainLayout = new QVBoxLayout(ui->customPlot);
    mainLayout->setMargin(0);
    mainLayout->addWidget(plot);
    mainLayout->setStretch(0, 1);

    // 创建矩形项
    QCPItemRect* rect = new QCPItemRect(plot);
    rect->topLeft->setCoords(0, 3);      // 左上角坐标（x1,y1）
    rect->bottomRight->setCoords(3, 0);  // 右下角坐标（x2,y2）
    rect->setPen(QPen(Qt::blue, 2));

    // 创建图片项
    QCPItemPixmap* pixmap = new QCPItemPixmap(plot);
    pixmap->setPixmap(QPixmap(":/image/plot.jpg"));
    // 加载图片并设置区域
    pixmap->topLeft->setCoords(4, 9);
    pixmap->bottomRight->setCoords(8, 2);
    // 启用缩放并设置边框
    pixmap->setScaled(true, Qt::KeepAspectRatio);
    pixmap->setPen(QPen(Qt::blue));


    DynamicPixmapBinder *binder = new DynamicPixmapBinder(plot);
    binder->addConnection(rect, pixmap);



//    // 初始化绑定管理器
//    DynamicPixmapBinder binder(plot);
//    binder.bindRectToPixmap(rect, pixmap);

//    // 动态测试（移动矩形右下角）
//    QTimer::singleShot(2000, [rect, plot](){
//        rect->bottomRight->setCoords(2, -1); // 触发图片位置自动更新
//        plot->replot();
//    });

}

void MainWindow::on_pushButton_save_clicked()
{
    // 生成Pixmap
    QPixmap pixmap = m_customPlot->toPixmap();

    PixmapWidget *p = new PixmapWidget(m_customPlot, pixmap);
    p->show();
    m_customPlot->SetupPixmapItem(pixmap);

}

void MainWindow::on_checkBox_srmZoom_clicked(bool checked)
{
    m_customPlot->EnableSRMZoom(checked);
}
